<?php

namespace App\Trip\Plane\PlaneInfo;

use App\Models\Orders\Repositories\Interfaces\OrderTripInfoInterface;
use App\Models\Plane\Airports\Airport;
use App\Models\Plane\Airports\Repositories\Interfaces\AirportRepositoryInterface;
use App\Trip\Traits\TimeTraits\ArriveDateTimeTrait;
use App\Trip\Traits\TimeTraits\DepartDateTimeTrait;
use App\Trip\Traits\TimeTraits\RunTimeTrait;
use Carbon\Carbon;
use Exception;
use Illuminate\Contracts\Support\Arrayable;
use JetBrains\PhpStorm\ArrayShape;

class FlightInfo implements Arrayable, OrderTripInfoInterface
{
    use DepartDateTimeTrait, ArriveDateTimeTrait, RunTimeTrait;

    private AirportRepositoryInterface $airportRepo;

    private string   $flight_no          = '';   // 航班号
    private string   $from_code          = '';   // 出发机场code
    private string   $to_code            = '';   // 目的机场 code
    private string   $from_tower         = '';   // 航站楼  可能为空
    private string   $to_tower           = '';   // 航站楼  可能为空
    private string   $arrive_at          = '';   // 到达日期时间  YYYY-mm-dd H:i
    private string   $depart_at          = '';   // 出发日期时间  YYYY-mm-dd H:i
    private int      $day_difference     = 0;    // 日差
    private int      $run_time           = 0;    // 时间
    private array    $basePrices         = [];   // 基础价格
    private array    $construction_fees  = [];   // 基建费
    private array    $fuel_fees          = [];   // 燃油费
    private array    $checkPrices        = [];   // 结算价格
    private string   $cabin_name         = '';   // 经济舱 头等舱
    private string   $child_cabin_name   = '';   // 儿童舱
    private array    $cabins             = [];   // 成人 => W ,儿童 =>Z
    private string   $cabin              = '';   // 主仓位  具体仓位 看乘客
    private string   $child_cabin        = '';   // 儿童舱 code
    private string   $provider_policy_id = '';   // 供应商政策
    private string   $discount           = '';   // 折扣
    private ?Airport $to_airport         = null;
    private ?Airport $from_airport       = null;

    public function __construct()
    {
        $this->airportRepo = app(AirportRepositoryInterface::class);
    }

    /**
     * @throws Exception
     */
    public function __get(string $name)
    {
        if (isset($this->$name)) {
            return $this->$name;
        }
        throw  new Exception("属性{$name}不存在");
    }

    public function __isset(string $name): bool
    {
        return isset($this->$name);
    }


    public function calcArriveAt(): string
    {
        return Carbon::parse($this->getDepartAt())->addMinutes($this->getRunTime())->toDateTimeString();
    }


    public function getTripDate(): string
    {
        return $this->getStartDate();
    }


    public function calcArriveDate(): string
    {
        return Carbon::parse($this->getStartDate())->addDays($this->getDayDifference())->toDateString();
    }


    /**
     * 供应商的价格
     * @param array $prices
     * @return void
     */
    public function setProviderPrices(array $prices): void
    {
        $this->basePrices = $prices;
    }

    public function getProviderPrices(): array
    {
        return $this->basePrices;
    }

    /**
     * 机建费
     * @param array $construction_fees
     * @return void
     */
    public function setProviderConstructionFees(array $construction_fees): void
    {
        $this->construction_fees = $construction_fees;
    }

    /**
     * 燃油费
     * @param array $fuel_fees
     * @return void
     */
    public function setProviderFuelFees(array $fuel_fees): void
    {
        $this->fuel_fees = $fuel_fees;
    }

    /**
     * @return array
     */
    public function getFuelFees(): array
    {
        return $this->fuel_fees;
    }

    /**
     * @return array
     */
    public function getConstructionFees(): array
    {
        return $this->construction_fees;
    }

    /**
     * 舱位
     * @return array
     */
    public function getCabins(): array
    {
        return $this->cabins;
    }

    public function setCabins(array $cabins): void
    {
        $this->cabins      = $cabins;
        $this->child_cabin = $this->cabins['child_cabin'] ?? '';
    }

    /**
     * @throws Exception
     */
    public function toArray(): array
    {
        return $this->getFlightInfo();
    }

    /**
     * @throws Exception
     */
    public function getFlightInfo(): array
    {
        $ret = [
            'flight_no'          => $this->getFlightNo(),
            'discount'           => $this->getDiscount(),
            'from_code'          => $this->getFromCode(),
            'from_tower'         => $this->getFromTower(),
            'to_tower'           => $this->getToTower(),
            'from_name'          => $this->getFromName(),
            'from_name_uy'       => $this->getFromNameUy(),
            'to_code'            => $this->getToCode(),
            'to_name'            => $this->getToName(),
            'to_name_uy'         => $this->getToNameUy(),
            'start_date'         => $this->getStartDate(),
            'arrive_date'        => $this->getArriveDate(),
            'start_time'         => $this->getStartTime(),
            'arrive_time'        => $this->getArriveTime(),
            'run_time'           => $this->getRunTime(),
            'day_difference'     => $this->getDayDifference(),
            'cabin_name'         => $this->getCabinName(),
            'cabin'              => $this->getCabin(),
            'child_cabin_name'   => $this->getChildCabinName(),
            'child_cabin'        => $this->getChildCabin(),
            'provider_policy_id' => $this->getProviderPolicyId(),
        ];

        // 保存 结算价格
        $ret['provider_prices'] = json_encode($this->getCheckPrices(), 64 | 256);
        $ret['check_prices']    = json_encode($this->getCheckPrices(), 64 | 256);
        return $ret;
    }

    /**
     * 航班号
     * @return string
     */
    public function getFlightNo(): string
    {
        return $this->flight_no;
    }

    public function setFlightNo(string $flight_no): void
    {
        $this->flight_no = $flight_no;
    }

    /**
     * @return string
     */
    public function getDiscount(): string
    {
        return $this->discount;
    }

    /**
     * @param string $discount
     */
    public function setDiscount(string $discount): void
    {
        $this->discount = $discount;

    }

    public function getFromCode(): string
    {
        return $this->from_code;
    }

    public function setFromCode(string $from_code): void
    {
        // 避免重写成其他
        if (!$this->from_code) {
            $this->from_code = $from_code;
        }
    }

    public function getFromTower(): string
    {
        return $this->from_tower;
    }

    public function setFromTower(string $from_tower): void
    {
        $this->from_tower = $from_tower;
    }

    public function getToTower(): string
    {
        return $this->to_tower;
    }

    public function setToTower(string $to_tower): void
    {
        $this->to_tower = $to_tower;
    }

    public function getFromName(): string
    {
        $from = $this->from_airport();
        return $from?->getName() ?: '';
    }

    public function from_airport(): ?Airport
    {
        if ($this->from_airport) {
            return $this->from_airport;
        }
        $this->from_airport = $this->airportRepo->findOneByCode($this->from_code);
        return $this->from_airport;
    }

    public function getFromNameUy(): string
    {
        $from = $this->from_airport();
        return $from?->getNameUy() ?: '';
    }

    public function getToCode(): string
    {
        return $this->to_code;
    }

    public function setToCode(string $to_code): void
    {
        if (!$this->to_code) {
            $this->to_code = $to_code;
        }
    }

    public function getToName(): string
    {
        $to = $this->to_airport();
        return $to?->getName() ?: '';
    }

    public function to_airport(): ?Airport
    {
        if ($this->to_airport) {
            return $this->to_airport;
        }
        $this->to_airport = $this->airportRepo->findOneByCode($this->to_code);
        return $this->to_airport;
    }

    public function getToNameUy(): string
    {
        $to = $this->to_airport();
        return $to?->getNameUy() ?: '';
    }

    public function getCabinName(): string
    {
        return $this->cabin_name;
    }

    public function setCabinName(string $cabin_name)
    {
        $this->cabin_name = $cabin_name;
    }

    public function getCabin(): string
    {
        return $this->cabin;
    }

    public function setCabin(string $cabin): void
    {
        $this->cabin = strtoupper($cabin);
    }

    private function getChildCabinName(): string
    {
        return $this->child_cabin_name;
    }

    private function getChildCabin(): string
    {
        return $this->child_cabin;
    }

    public function getProviderPolicyId(): string
    {
        return $this->provider_policy_id ?? '';
    }

    public function setProviderPolicyId(string $provider_policy_id): void
    {
        $this->provider_policy_id = $provider_policy_id;
    }

    /**
     * 结算价格 也就是实际售卖价格
     * @return array
     */
    #[ArrayShape([
        'adult_price',
        'child_price',
        'baby_price',
    ])]
    public function getCheckPrices(): array
    {
        return $this->checkPrices;
    }

    /**
     * 结算价格
     * @param array $prices
     * @return void
     */
    public function setCheckPrices(array $prices): void
    {
        $this->checkPrices = $prices;
    }


}